<script setup lang="ts">
import { h, VNode } from "vue";

type Tree = {
  label: string;
  children?: Tree;
}[]

/** 父子组件通信 */
const props = defineProps<{
  data: Tree,
}>()

/** 自定义事件 */
const emit = defineEmits([
  'nodeClick'
])

/** 创建非叶节点 */
const create_node = (e: { label: string }) => {
  const ico = h("div", { class: "zh-tree_ico" });
  const label = h("div", { class: "zh-tree_label" }, e.label);
  const node = h("div", {
    class: "node", onClick: () => {
      if (ico.el && node.el) {
        // 展开
        if (!ico.el.className.includes("zh-tree_ico_down")) {
          ico.el.className = "zh-tree_ico zh-tree_ico_down";
          // 获取高度
          node.el.nextSibling.style.height = "auto";
          const height = node.el.nextSibling.offsetHeight;
          // 设置为零
          node.el.nextSibling.style.height = 0;
          node.el.nextSibling.offsetHeight;
          // 还原高度
          node.el.nextSibling.style.height = height + "px";
          setTimeout(() => {
            if (node.el) {
              node.el.nextSibling.style.height = "auto";
            }
          }, 500)
        }
        // 缩进
        else {
          ico.el.className = "zh-tree_ico";
          // 获取高度
          node.el.nextSibling.style.height = "auto";
          const height = node.el.nextSibling.offsetHeight;
          // 设置高度
          node.el.nextSibling.style.height = height + "px";
          node.el.nextSibling.offsetHeight;
          // 还原为零
          node.el.nextSibling.style.height = 0;
        }
      }
      emit('nodeClick', e);
    }
  }, [ico, label]);
  return node;
}

/** 创建叶子节点 */
const create_leaf = (e: { label: string }) => {
  const label = h("div", { class: "zh-tree_label" }, e.label);
  const leaf = h("div", {
    class: "leaf", onClick: () => {
      emit('nodeClick', e);
    }
  }, [label]);
  return leaf;
}

/** 创建子树 */
const create_brach = (list: Tree) => {
  const brachs: VNode[] = [];
  // 层遍历
  for (const e of list) {
    // 若有子树
    if (e.children && e.children.length > 0) {
      // 添加一个非叶节点
      const node = create_node(e);
      brachs.push(node);
      // 往下递归
      const subTree = create_brach(e.children);
      brachs.push(subTree);
    }
    else {
      // 添加一个叶子节点
      const leaf = create_leaf(e);
      brachs.push(leaf);
    }
  }
  // 添加一颗子树
  const brach = h("div", { class: "brach" }, brachs);
  return brach;
}

/** 创建树状结构 */
const create_tree = (list: Tree) => {
  const brach = create_brach(list);
  // 最外层为tree
  if (brach.props) {
    brach.props.class = "tree"
  }
  return brach;
}

const tree = create_tree(props.data);

const ZhTree = h("div", { class: "zh-tree" }, [tree]);
</script>

<template>
  <zh-tree />
</template>

<style>
.brach {
  overflow: hidden;
  padding-left: 1.2rem;
  height: 0;
  transition: 0.5s;
  cursor: pointer;
}

.expanded {
  height: auto;
}

.node {
  display: flex;
  align-items: center;
  padding: 0.5rem;
}

.node:hover {
  background: #eee;
}


.leaf {
  display: flex;
  align-items: center;
  padding: 0.5rem;
}

.leaf:hover {
  background: #eee;
}


.zh-tree_ico {
  margin-right: 5px;
  width: 0;
  height: 0;
  border-left: 0.7rem solid #378;
  border-top: 0.5rem solid transparent;
  border-bottom: 0.5rem solid transparent;
  transition: transform 0.5s;
}

.zh-tree_ico_down {
  transform: rotate(90deg);
}

.zh-tree_label {
  color: #345;
  font-size: 14px;
}
</style>
